#include "print.h"

extern void myPrintfDebug (int, char);

#define rowMax 25
#define colMax 80

int cursorRow = 0;
int cursorCol = 0;

static int convert (int, int);
static void cursorGetIncSlashN ();
static void flush ();

void printInit ()
{
  flush ();
  cursorRow = 0;
  cursorCol = 0;
}

int cursorGetInc ()
{
  int current = convert (cursorRow, cursorCol);
  
  cursorCol++;
  if (cursorCol==colMax)
  {
    cursorRow++;
    cursorCol=0;
  }
  if (cursorRow==rowMax)
  {
    flush ();
    cursorRow = 0;
  }

  return current;
}

void cursorGetIncSlashN ()
{
  cursorRow++;
  cursorCol = 0;
  
  if (cursorRow==rowMax)
  {
    flush ();
    cursorRow = 0;
  }
}

void printStr (char *str)
{
  char *temp = str;

  while (*temp)
  {
    char c = *temp;
    
    switch (c)
    {
    case '\n':
      cursorGetIncSlashN ();
      break;
    default:
      myPrintfDebug (cursorGetInc (), c);
      break;
    }
    
    temp++;
  }
  return;
}


static void flush ()
{
  for (int row=0; row<25; row++)
    for (int col=0; col<80; col++)
      myPrintfDebug ((row*80+col)*2, ' ');

  return;
}

void printInt (int i)
{
  int abs;
  int withSign;

  if (i<0)
  {
    withSign = 1;
    abs = 0-i;
  }
  else
  {
    withSign = 0;
    abs = i;
  }
  
  char buf[100];
  
  int tail = 0;
 
  while (abs>=10)
  {
    buf[tail++] = abs%10 + 48;
    abs = abs/10;
  }
  if (abs)
    buf[tail++] = abs + 48;

  if (withSign)
    buf[tail++] = '-';
  
  char temp;
  for (int i=0; i<(tail-1)/2; i++)
  {
    temp = buf[i];
    buf[i] = buf[tail-1-i];
    buf[tail-1-i] = temp;
  }
  buf[tail] = '\0';
  printStr (buf);

  return;
}

// Recall that the "printf()" function in C library returns "int"
// We make some simplifications here.
void myPrintf (char *format, ...)
{
  
  int *firstArgPtr = &format;
  firstArgPtr++;

  char *temp = (char *)format;
  int t;

  while (*temp)
  {
    char c = *temp;
    switch (c)
    {
    case '%':
      {
	temp++;
	char c1 = *temp;
	switch (c1)
	  {
	  case 'd':
            t = *firstArgPtr;
	    printInt (t);
	    firstArgPtr++;
	    break;
	  case '%':
	    printStr ("%");
	    break;
	  default:
	    printStr ("error in kernel: print.c\n");
	    break;
	  }
	break;
      }
    case '\n':
      cursorGetIncSlashN ();
      break;
    default:
      myPrintfDebug (cursorGetInc (), c);
      break;
    }
    temp++;
  }
  return;
}

static int convert (int row, int col)
{
  return (row*80+col)*2;
}
